# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.676.12.15 -> 1.676.12.16
#	arch/ia64/kernel/signal.c	1.7     -> 1.8    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/09/27	davidm@tiger.hpl.hp.com	1.676.12.16
# ia64: Fix narrow window during which signal could be delivered with only the memory
#       stack switched over to the alternate signal stack.
# --------------------------------------------
#
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Wed Oct  8 09:09:17 2003
+++ b/arch/ia64/kernel/signal.c	Wed Oct  8 09:09:17 2003
@@ -354,6 +354,15 @@
 	return err;
 }
 
+/*
+ * Check whether the register-backing store is already on the signal stack.
+ */
+static inline int
+rbs_on_sig_stack (unsigned long bsp)
+{
+	return (bsp - current->sas_ss_sp < current->sas_ss_size);
+}
+
 static long
 setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	     struct sigscratch *scr)
@@ -366,10 +375,15 @@
 
 	frame = (void *) scr->pt.r12;
 	tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section);
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack((unsigned long) frame)) {
-		new_rbs  = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
-		frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
-				  & ~(STACK_ALIGN - 1));
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		/* We need to check the memory and register stacks separately, because
+		   they're switched separately (memory stack is switched in the kernel,
+		   register stack is switched in the signal trampoline.  */
+		if (!on_sig_stack((unsigned long) frame))
+			frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
+					  & ~(STACK_ALIGN - 1));
+		if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
+			new_rbs  = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
 	}
 	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));